package com.java.jvalidator.framework.validator;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import com.java.jvalidator.framework.TypeUtil;
import com.java.jvalidator.framework.ValidationException;
import com.java.jvalidator.framework.ValidationExceptionMsg;
import com.java.jvalidator.framework.XMLConfigConst;
import com.java.jvalidator.framework.config.Parameters;

public class RegExValidator extends AbstractValidator {
	private static final String PROPERTY_NAME = ",Property Name:";
	private static final String VALIDATION_CLASS = "\tValidation Class:";
	private static final String ERROR = " ERROR!\n";
	private static final String REGEX = "Regex :";
	private static Validator instance = new RegExValidator();

	public static Validator getInstance() {
		return instance;
	}

	protected boolean beginValidate(Object target, String fieldName, Parameters param) throws ValidationException {
		Object fieldValue = TypeUtil.getPropertyValue(target, fieldName);
		if (fieldValue == null) {
			return true;
		}
		if (param == null) {
			throw new ValidationException(ValidationExceptionMsg.VALIDATION_PARAMETER_ERROR);
		}
		if (!(fieldValue instanceof String)) {
			throw new ValidationException(ValidationExceptionMsg.VALIDATION_ERROR);
		}
		String patternStr = param.getParameterValueAsString(XMLConfigConst.PATTERN);
		if (TypeUtil.isStringNullOrEmpty(patternStr)) {
			throw new ValidationException(ValidationExceptionMsg.VALIDATION_PARAMETER_ERROR);
		}
		String str = (String) fieldValue;
		if (TypeUtil.isStringNullOrEmpty(str)) {
			return true;
		}
		Pattern pattern = null;
		try {
			// Pattern.DOTALL 点号能够匹配换行符
			// Pattern.MULTILINE ^和$可以匹配字符串内部换行符
			// Pattern.COMMENTS 注释模式
			// Pattern.CASE_INSENSITIVE 对ASCII字符进行不区分大小写匹配
			// Pattern.UNICODE_CASE 对Unicode字符进行不区分大小写匹配
			// Pattern.CANNON_EQ 不同的编码中相同的字符视为相等
			// Pattern.LITERAL 纯文本模式
			pattern = Pattern.compile(patternStr, Pattern.DOTALL);
		} catch (PatternSyntaxException exception) {
			throw new ValidationException(REGEX + patternStr + ERROR + VALIDATION_CLASS + target.getClass().getName() + PROPERTY_NAME + fieldName + "\n" + exception.getMessage());
		}
		Matcher matcher = pattern.matcher(str);

		// match的作用其实就是为了取反，比如，要匹配非数字，可以像下面这样写 match="false"
		// <regex pattern="[0-9]{1,31}" conditionProperty="otherPropertyName" conditionValue="[^\t\n]+" errorMsg=".." match="false"/>
		// 也就是，匹配[0-9]{1,31}就报错
		String match = param.getParameterValueAsString(XMLConfigConst.MATCH);
		if ((match == null) || (match.trim().length() == 0)) {
			return matcher.matches();
		}
		return matcher.matches() == (!XMLConfigConst.FALSE.equalsIgnoreCase(match));
	}
}
